package net.aiion.weave.spi.xml;

import java.util.Collection;
import java.util.ServiceLoader;

import net.aiion.weave.spi.xml.events.AttributeXmlEvent;
import net.aiion.weave.spi.xml.events.CharactersXmlEvent;
import net.aiion.weave.spi.xml.events.CommentXmlEvent;
import net.aiion.weave.spi.xml.events.DocumentEndXmlEvent;
import net.aiion.weave.spi.xml.events.DocumentStartXmlEvent;
import net.aiion.weave.spi.xml.events.DocumentTypeDefinitionXmlEvent;
import net.aiion.weave.spi.xml.events.ElementEndXmlEvent;
import net.aiion.weave.spi.xml.events.ElementStartXmlEvent;
import net.aiion.weave.spi.xml.events.NamespaceXmlEvent;
import net.aiion.weave.spi.xml.events.ProcessingInstructionXmlEvent;
import net.aiion.weave.spi.xml.events.SourceXmlEvent;

public abstract class XmlEventFactory
{
    private static XmlEventFactory xmlEventFactoryInstance;

    public XmlEventFactory() {
    }

    public abstract XmlQualifiedName createQualifiedName(String aLocalName);

    public abstract XmlQualifiedName createQualifiedName(String aNamespaceURI, String aLocalName);

    public abstract XmlQualifiedName createQualifiedName(String aNamespaceURI, String aLocalName, String aPrefix);

    public abstract SourceXmlEvent createSource(String aSourceFileName);

    public abstract DocumentStartXmlEvent createDocumentStart();

    public abstract DocumentStartXmlEvent createDocumentStart(String aVersion);

    public abstract DocumentStartXmlEvent createDocumentStart(String aVersion, String aEncoding);

    public abstract DocumentStartXmlEvent createDocumentStart(String aVersion, String aEncoding, boolean aStandalone);

    public abstract DocumentTypeDefinitionXmlEvent createDocumentTypeDefinition(String aDocumentTypeDefinition);

    public abstract CommentXmlEvent createComment(String aComment);

    public abstract ProcessingInstructionXmlEvent createProcessingInstruction(String aTarget, String aData);

    public abstract ElementStartXmlEvent createElementStart(String aPrefix, String aNamespaceURI, String aLocalName);

    public abstract ElementStartXmlEvent createElementStart(String aPrefix, String aNamespaceURI, String aLocalName,
        Collection<AttributeXmlEvent> aXmlAttributes, Collection<NamespaceXmlEvent> aXmlNamespaces);

    public abstract ElementStartXmlEvent createElementStart(XmlQualifiedName aXmlQualifiedName);

    public abstract ElementStartXmlEvent createElementStart(XmlQualifiedName aXmlQualifiedName,
        Collection<AttributeXmlEvent> aXmlAttributes, Collection<NamespaceXmlEvent> aXmlNamespaces);

    public abstract NamespaceXmlEvent createNamespace(String aNamespaceURI);

    public abstract NamespaceXmlEvent createNamespace(String aPrefix, String aNamespaceURI);

    public abstract AttributeXmlEvent createAttribute(String aPrefix, String aNamespaceURI, String aLocalName,
        String aValue);

    public abstract AttributeXmlEvent createAttribute(XmlQualifiedName aXmlQualifiedName, String aValue);

    public abstract CharactersXmlEvent createCharacters(String aCharacters);

    public abstract CharactersXmlEvent createCharacters(String aCharacters, int aCharacterDataType);

    public abstract ElementEndXmlEvent createElementEnd(String aPrefix, String aNamespaceURI, String aLocalName);

    public abstract ElementEndXmlEvent createElementEnd(XmlQualifiedName aXmlQualifiedName);

    public abstract DocumentEndXmlEvent createDocumentEnd();

    public static XmlEventFactory getInstance() {
        if (xmlEventFactoryInstance == null) {
            for (XmlEventFactory xmlEventFactory : XmlEventFactoryServiceLoader.SERVICE_LOADER) {
                xmlEventFactoryInstance = xmlEventFactory;
                break;
            }
        }

        return xmlEventFactoryInstance;
    }

    private static final class XmlEventFactoryServiceLoader
    {
        private static final ServiceLoader<XmlEventFactory> SERVICE_LOADER = ServiceLoader.load(XmlEventFactory.class);

        private XmlEventFactoryServiceLoader() {
        }
    }
}
